package chips440.internals;

import java.util.ArrayList;

import chips440.tiles.Tile;
import chips440.tiles.NormalTile;
import chips440.tiles.DoorTile;
import chips440.main.Cell;

/**
 * Contains information about a board for chips440.
 *
 * Boards are to be created using BoardParser. Abstractly boards are
 * infinite -- if a Board is queried for a point outside of the defined map,
 * it simply returns a NormalTile.
 *
 * @author Ian Voysey
 * @version 0.1
 */
public class Board{
    private Tile tile_matrix [][];
    private Cell player_position;
    private int max_time, max_chip;
    private NormalTile normalTile; // a saved blank space for getTile

    /**
     * Creates a new board with the specified dimension, time, and chip
     * count. All boards are considered to be square in stored form to
     * simplify their storage, but infinite when accessed.
     *
     * @param dim the size of the square needed to store the board
     * @param max_time the maximum number of seconds a player is given to
     * complete the level
     * @param max_chip the number of chips that must be collected to complete
     * the map
     */
    public Board(int dim, int max_time, int max_chip){
 	tile_matrix = new Tile [dim][dim];

	this.max_time = max_time;
	this.max_chip = max_chip;
	this.normalTile = new NormalTile();
    }

    /**
     * Returns the number of seconds afforded the player to complete the map.
     */
    public int getMaxTime(){ return max_time; }

    /**
     * Returns the number of chips the user must collect to complete the map.
     */
    public int getMaxChip(){ return max_chip; }

    /**
     * The positions of the players on the board
     *
     * @return an array list of Cell's, each of which is considered
     * to have a player on it
     */
    public Cell getPlayerPosition(){
	return player_position;
    }

    /**
     * Returns the type of tile positioned at (r,c). (0,0) is defined to be
     * the furthest non-regular tile to the upper left of the map. This method
     * never should return null; if it is queried for a tile that is outside
     * the scope of the original map file, it will return a NormalTile
     *
     * @param r the row of the board whose tile we're interested
     * @param c the column of the board whose tile we're interested
     * @return the tile located at (r,c)
     */
    public Tile getTile(int r, int c){
	if(r < 0 || c < 0 || r >= tile_matrix.length || c >= tile_matrix.length)
	    return this.normalTile;
	Tile tile = tile_matrix[r][c];
	if(tile == null)
	    return this.normalTile;
	return tile;
    }

    /**
     * Sets the type of Tile stored at a location.
     *
     * @param r the row to set
     * @param c the col to set
     * @param tile the type of tile to place at (r,c). If this is null, a new
     * NormalTIle will be placed at (r,c).
     */
    protected void setTile(int r, int c, Tile tile){
	if(tile == null)
	    tile = this.normalTile;
	else 	    
	    tile_matrix[r][c] = tile;
    }
    
    /**
     * Sets the initial player position
     *
     * @param r the r coordinate for the player to start at
     * @param c the c coordinate for the player to start at
     */
    protected void setInitPlayerPos(int r, int c){
	player_position = new Cell(r,c);
    }

    /**
     * This method removes a door from the map at the particular location, if
     * it exists.
     *
     * @param r the row of the supposed door
     * @param c the column of the supposed door
     */
    public void knockDown(int r, int c){
        try{
            tile_matrix[r][c] = (DoorTile)tile_matrix[r][c];
            tile_matrix[r][c] = this.normalTile;
        }catch(Exception e){
            return;
        }
    }
}
